Skip to content

Avro: read a file without avro.codec as uncompressed - #4296

Merged
kevinjqliu merged 1 commit into
apache:mainfrom
jatorre:avro-missing-codec-is-null
Nov 9, 2026
Merged

kevinjqliu merged 1 commit into
apache:mainfrom
jatorre:avro-missing-codec-is-null

Conversation

@jatorre

@jatorre jatorre commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Closes #4295

Rationale for this change

AvroFileHeader.compression_codec() read a missing avro.codec entry as TableProperties.WRITE_AVRO_COMPRESSION_DEFAULT ("gzip"), an Iceberg property value rather than an Avro codec name, and raised Unsupported codec: gzip. The Avro specification makes null the default, so a file without the entry is uncompressed. iceberg-rust writes manifests that way (apache/iceberg-rust#3640), so PyIceberg could not scan a table with a snapshot committed from iceberg-rust.

The writer side (AvroOutputFile._write_header) is unchanged: it still writes the entry, mapping the Iceberg name to the Avro one.

Are these changes tested?

test_missing_codec_is_null in tests/avro/test_file.py (it fails on main with the error above). tests/avro/test_file.py and tests/avro/test_reader.py pass (41); ruff is clean. End to end: a table on a REST catalog whose second snapshot was committed from iceberg-rust (manifest without the entry). PyIceberg 0.12 as released raises Unsupported codec: gzip on scan(); with this one-line change applied to the installed 0.12 it reads all 3,000 rows.

Are there any user-facing changes?

Avro files without avro.codec are now read instead of refused.

AI disclosure: drafted with Claude Code (Claude Opus 5.5) at my direction; I ran the tests and ruff.

The Avro specification makes null the default codec. PyIceberg fell back to the Iceberg table
property default (gzip), which is not an Avro codec name, so it raised 'Unsupported codec: gzip' on
manifests written without the entry (iceberg-rust writes them so).

@AP24110011695 AP24110011695 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified locally (Windows, Python 3.12):

  • test_missing_codec_is_null and the existing codec tests pass on this branch.
  • On the pre-change code the same call raises ValueError: Unsupported codec: gzip — the fail-first claim reproduces exactly.
  • Checked all three WRITE_AVRO_COMPRESSION_DEFAULT fallback sites: the reader (AvroFileHeader.compression_codec) is the only one reading file metadata, where the Avro spec's null default is the correct semantic; the two writer sites (_write_header, AvroOutputFile.compression_codec) read write-task configuration, where the Iceberg property default is intentional — leaving them unchanged is right.
  • Blast radius is one line: files that have avro.codec take the same path as before.

Spec-based, minimal, tested, and unblocks iceberg-rust-written manifests (references apache/iceberg-rust#3640). Nice catch.

@kevinjqliu kevinjqliu left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

quick script to verify

uv run --no-sync --with avro python <<'PY'
from avro.schema import parse
from avro.io import DatumWriter
from avro.datafile import DataFileWriter
from pyiceberg.avro.file import AvroFile
from pyiceberg.io.pyarrow import PyArrowFileIO

schema = parse('''{
    "type": "record",
    "name": "example",
    "fields": [{"name": "id", "type": "long", "field-id": 1}]
}''')

with DataFileWriter(open("test.avro", "wb"), DatumWriter(), schema) as writer:
    del writer.codec
    writer.append({"id": 42})

with AvroFile(PyArrowFileIO().new_input("test.avro")) as reader:
    print(list(reader))
PY

BEFORE: Unsupported codec: gzip
AFTER: [Record[42]]

Comment thread pyiceberg/avro/file.py
from pyiceberg.table import TableProperties

codec_name = self.meta.get(AVRO_CODEC_KEY, TableProperties.WRITE_AVRO_COMPRESSION_DEFAULT)
codec_name = self.meta.get(AVRO_CODEC_KEY, "null")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinjqliu
kevinjqliu added this pull request to the merge queue Nov 9, 2026
@kevinjqliu

Copy link
Copy Markdown
Contributor

Thank you for the fix @jatorre and thanks for the reviews @AP24110011695 @ebyhr

Merged via the queue into apache:main with commit 2549061 Nov 9, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avro reader treats a missing avro.codec as gzip and raises 'Unsupported codec: gzip'

4 participants